home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dicecache / main.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  8KB  |  406 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  MAIN.C
  9.  */
  10.  
  11. #include "defs.h"
  12.  
  13. #ifdef AMIGA
  14. #include <lib/version.h>
  15.  
  16. #ifdef _DCC
  17. IDENT("dicecache.library",".58");
  18. DCOPYRIGHT;
  19. #endif
  20. #endif
  21.  
  22. Prototype LibCall CacheNode *DiceCacheOpen(__A0 const char *, __A1 const char *, __A2 long *);
  23. Prototype LibCall void DiceCacheClose(__A0 CacheNode *);
  24. Prototype LibCall void *DiceCacheSeek(__A0 CacheNode *, __D0 long, __A1 long *);
  25. Prototype LibCall long DiceCacheGetSuffixes(__A0 char *, __D0 long);
  26. Prototype LibCall long DiceCacheAddSuffix(__A0 const char *);
  27. Prototype LibCall long DiceCacheRemSuffix(__A0 const char *);
  28. Prototype LibCall void DiceCacheFlush(__D0 long);
  29. Prototype LibCall void DiceCacheSet(__A0 long *, __D0 long);
  30. Prototype LibCall void DiceCacheGet(__A0 long *, __D0 long);
  31. Prototype LibCall void DiceCacheEnable(void);
  32. Prototype LibCall void DiceCacheDisable(void);
  33.  
  34. Prototype char      Buf[1024];
  35. Prototype long      CachedBytes;
  36. Prototype long      CachedBytesLocked;
  37. Prototype long      CacheMaxFile;
  38. Prototype long      CacheMax;
  39. Prototype short   CacheEnabled;
  40.  
  41. char    Buf[1024];
  42. long    CachedBytes;
  43. long    CachedBytesLocked;
  44. long    CacheMaxFile;
  45. long    CacheMax;
  46. long    CacheHits1;
  47. long    CacheHits2;
  48. long    CacheAttempts1;
  49. long    CacheAttempts2;
  50. short    CacheEnabled;
  51.  
  52. LibCall
  53. CacheNode *
  54. DiceCacheOpen(fileName, fileModes, psize)
  55. __A0 const char *fileName;
  56. __A1 const char *fileModes;
  57. __A2 long *psize;
  58. {
  59.     BPTR lock;
  60.     CacheNode *cn;
  61.  
  62.     /*
  63.      *    Only for read access
  64.      */
  65.  
  66.     *psize = 0;
  67.     if (CacheEnabled == 0)
  68.     return(NULL);
  69.  
  70.     dbprintf(("Cached %d/%d/%d\n", CachedBytesLocked, CachedBytes, CacheMax));
  71.  
  72.     if (strchr(fileModes, '+') || strchr(fileModes, 'a') || strchr(fileModes, 'w'))
  73.     return(NULL);
  74.  
  75.     ObtainSemaphore(&SemLock);
  76.  
  77.     dbprintf(("open/lock\n"));
  78.  
  79.     /*
  80.      *    Step 1, check for suffix match
  81.      */
  82.  
  83.     {
  84.     short len = strlen(fileName);
  85.     Node *node;
  86.  
  87.     for (node = GetHead(&SuffixList); node; node = GetSucc(node)) {
  88.         if (node->ln_Pri < len && stricmp(node->ln_Name, fileName + len - node->ln_Pri) == 0)
  89.         break;
  90.     }
  91.     if (node == NULL) {
  92.         ReleaseSemaphore(&SemLock);
  93.         *psize = PS_NO_MATCH;
  94.         return(NULL);
  95.     }
  96.     }
  97.  
  98.     /*
  99.      *    Step 2, obtain lock on directory containing file and determine
  100.      *    whether the file is cached.
  101.      */
  102.  
  103.     {
  104.     short len = MyPathPart(fileName) - fileName;
  105.     strncpy(Buf, fileName, len);
  106.     Buf[len] = 0;
  107.     }
  108.  
  109.     if ((lock = Lock(Buf, SHARED_LOCK)) == NULL) {
  110.     ReleaseSemaphore(&SemLock);
  111.     *psize = PS_LOCK_FAILED;
  112.     return(NULL);
  113.     }
  114.  
  115.     *psize = PS_GENERAL_FAILURE;    /*    replaced w/ size if success */
  116.  
  117.     strcpy(Buf, MyFilePart(fileName));
  118.  
  119.     if (CacheAttempts1 == 100) {
  120.     CacheAttempts2 = CacheAttempts1;
  121.     CacheHits2 = CacheHits1;
  122.     CacheAttempts1 = 0;
  123.     CacheHits1 = 0;
  124.     }
  125.     ++CacheAttempts1;
  126.     if (cn = FindCache(lock, Buf)) {
  127.     ++CacheHits1;
  128.  
  129.     UnLock(lock);
  130.     if (cn->cn_Refs++ == 0)
  131.         CachedBytesLocked += cn->cn_Bytes;
  132.     *psize = cn->cn_Bytes;
  133.     } else {
  134.     long siz;
  135.     long fh;
  136.  
  137.     if (fh = Open(fileName, 1005)) {
  138.         Seek(fh, 0L, 1);
  139.         if ((siz = Seek(fh, 0L, -1)) > 0 && siz < CacheMaxFile) {
  140.         ClearCache(siz);
  141.         if (cn = AllocMem(sizeof(CacheNode) + strlen(Buf) + 1, MEMF_PUBLIC|MEMF_CLEAR)) {
  142.             cn->cn_Lock = lock;
  143.             cn->cn_Node.ln_Name = (char *)(cn + 1);
  144.             strcpy(cn->cn_Node.ln_Name, Buf);
  145.             AddCache(cn);
  146.  
  147.             if (cn->cn_Data = AllocMem(siz + 4, MEMF_PUBLIC)) {
  148.             *(long *)((char *)cn->cn_Data + siz) = 0;
  149.             cn->cn_Bytes = siz;
  150.             CachedBytes += siz;
  151.  
  152.             if (Read(fh, cn->cn_Data, siz) == siz) {
  153.                 cn->cn_Flags |= CNF_VALID;
  154.                 *psize = siz;
  155.             }
  156.             }
  157.         }
  158.         }
  159.         Close(fh);
  160.     } else {
  161.         /*
  162.          *    If the file doesn't exist then it isn't really our fault.
  163.          */
  164.  
  165.         ++CacheHits1;
  166.     }
  167.     if (cn) {
  168.         if ((cn->cn_Flags & CNF_VALID) == 0) {
  169.         DiceCacheClose(cn);
  170.         cn = NULL;
  171.         } else {
  172.         ++cn->cn_Refs;
  173.         CachedBytesLocked += cn->cn_Bytes;
  174.         }
  175.     } else {
  176.         UnLock(lock);
  177.     }
  178.     }
  179.  
  180.     ReleaseSemaphore(&SemLock);
  181.     return(cn);
  182. }
  183.  
  184. LibCall
  185. void
  186. DiceCacheClose(cn)
  187. __A0 CacheNode *cn;
  188. {
  189.     ObtainSemaphore(&SemLock);
  190.     if (--cn->cn_Refs == 0) {
  191.     CachedBytesLocked -= cn->cn_Bytes;
  192.     if (cn->cn_Flags & CNF_UNFIND)
  193.         --cn->cn_Refs;
  194.     }
  195.     if (cn->cn_Refs < 0) {
  196.     Remove(&cn->cn_Node);
  197.     if (cn->cn_Lock) {
  198.         UnLock(cn->cn_Lock);
  199.         cn->cn_Lock = 0;
  200.     }
  201.     if (cn->cn_Bytes) {
  202.         FreeMem(cn->cn_Data, cn->cn_Bytes + 4);
  203.         CachedBytes -= cn->cn_Bytes;
  204.     }
  205.     FreeMem(cn, sizeof(CacheNode) + strlen(cn->cn_Node.ln_Name) + 1);
  206.     }
  207.     ReleaseSemaphore(&SemLock);
  208. }
  209.  
  210. LibCall
  211. void *
  212. DiceCacheSeek(cn, off, pbsize)
  213. __A0 CacheNode *cn;
  214. __D0 long off;
  215. __A1 long *pbsize;
  216. {
  217.     if (off < 0 || off > cn->cn_Bytes) {
  218.     *pbsize = 0;
  219.     return(NULL);
  220.     }
  221.     *pbsize = cn->cn_Bytes - off;
  222.     return((void *)(cn->cn_Data + off));
  223. }
  224.  
  225. LibCall
  226. long
  227. DiceCacheGetSuffixes(buf, max)
  228. __A0 char *buf;
  229. __D0 long max;
  230. {
  231.     Node *node;
  232.     long r = 0;
  233.     short first = 0;
  234.     char *ptr = buf;
  235.  
  236.     --max;
  237.  
  238.     ObtainSemaphore(&SemLock);
  239.     for (node = GetHead(&SuffixList); node; node = GetSucc(node)) {
  240.     short len = strlen(node->ln_Name);
  241.  
  242.     if (len >= max) {
  243.         r -= len + 1;
  244.     } else {
  245.         if (first == 0) {
  246.         *ptr++ = ' ';
  247.         --max;
  248.         }
  249.         strcpy(ptr, node->ln_Name);
  250.         ptr += len;
  251.         max -= len;
  252.     }
  253.     }
  254.     ReleaseSemaphore(&SemLock);
  255.     if (r < 0)
  256.     return(r);
  257.     return(ptr - buf);
  258. }
  259.  
  260. LibCall
  261. long
  262. DiceCacheAddSuffix(buf)
  263. __A0 const char *buf;
  264. {
  265.     Node *node;
  266.     long r;
  267.  
  268.     ObtainSemaphore(&SemLock);
  269.     DiceCacheRemSuffix(buf);
  270.     if (node = AllocMem(sizeof(Node) + strlen(buf) + 1, MEMF_PUBLIC|MEMF_CLEAR)) {
  271.     node->ln_Name = (char *)(node + 1);
  272.     node->ln_Pri = strlen(buf);
  273.     strcpy(node->ln_Name, buf);
  274.     AddHead(&SuffixList, node);
  275.     r = 0;
  276.     } else {
  277.     r = -1;
  278.     }
  279.     ReleaseSemaphore(&SemLock);
  280.     return(r);
  281. }
  282.  
  283. LibCall
  284. long
  285. DiceCacheRemSuffix(buf)
  286. __A0 const char *buf;
  287. {
  288.     Node *node;
  289.     long r = -1;
  290.  
  291.     ObtainSemaphore(&SemLock);
  292.     for (node = GetHead(&SuffixList); node; node = GetSucc(node)) {
  293.     if (stricmp(buf, node->ln_Name) == 0) {
  294.         Remove(node);
  295.         FreeMem(node, sizeof(Node) + strlen(node->ln_Name) + 1);
  296.         r = 0;
  297.         break;
  298.     }
  299.     }
  300.     ReleaseSemaphore(&SemLock);
  301.     return(r);
  302. }
  303.  
  304. LibCall
  305. void
  306. DiceCacheFlush(bytes)
  307. __D0 long bytes;
  308. {
  309.     ObtainSemaphore(&SemLock);
  310.     ClearCache(bytes);
  311.     ReleaseSemaphore(&SemLock);
  312. }
  313.  
  314. LibCall
  315. void
  316. DiceCacheSet(la, n)
  317. __A0 long *la;
  318. __D0 long n;
  319. {
  320.     short i;
  321.  
  322.     ObtainSemaphore(&SemLock);
  323.     for (i = 0; i < n && i < 4; ++i, ++la) {
  324.     switch(i) {
  325.     case 0:
  326.         /*CachedBytesLocked = *la;*/
  327.         break;
  328.     case 1:
  329.         /*CachedBytes = *la;*/
  330.         break;
  331.     case 2:
  332.         CacheMax = *la;
  333.         break;
  334.     case 3:
  335.         CacheMaxFile = *la;
  336.         break;
  337.     }
  338.     }
  339.     ClearCache(CachedBytes - CacheMax);
  340.     ReleaseSemaphore(&SemLock);
  341. }
  342.  
  343. LibCall
  344. void
  345. DiceCacheGet(la, n)
  346. __A0 long *la;
  347. __D0 long n;
  348. {
  349.     short i;
  350.  
  351.     ObtainSemaphore(&SemLock);
  352.     for (i = 0; i < n; ++i, ++la) {
  353.     switch(i) {
  354.     case 0:
  355.         *la = CachedBytesLocked;
  356.         break;
  357.     case 1:
  358.         *la = CachedBytes;
  359.         break;
  360.     case 2:
  361.         *la = CacheMax;
  362.         break;
  363.     case 3:
  364.         *la = CacheMaxFile;
  365.         break;
  366.     case 4:
  367.         *la = CacheHits2 + CacheHits1;
  368.         break;
  369.     case 5:
  370.         *la = CacheAttempts2 + CacheAttempts1;
  371.         break;
  372.     default:
  373.         *la = 0;
  374.         break;
  375.     }
  376.     }
  377.     ReleaseSemaphore(&SemLock);
  378. }
  379.  
  380. LibCall
  381. void
  382. DiceCacheEnable(void)
  383. {
  384.     ObtainSemaphore(&SemLock);
  385.     if (CacheEnabled == 0) {
  386.     CacheEnabled = 1;
  387.     ++LibBase->lib_OpenCnt;
  388.     }
  389.     ReleaseSemaphore(&SemLock);
  390. }
  391.  
  392. LibCall
  393. void
  394. DiceCacheDisable(void)
  395. {
  396.     ObtainSemaphore(&SemLock);
  397.     if (CacheEnabled) {
  398.     CacheEnabled = 0;
  399.     --LibBase->lib_OpenCnt;
  400.     }
  401.     ReleaseSemaphore(&SemLock);
  402. }
  403.  
  404.  
  405.  
  406.